package com.ashlikun.camera.scan.manager;

import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

import androidx.annotation.NonNull;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.MeteringPoint;
import androidx.camera.core.ZoomState;
import androidx.camera.view.PreviewView;

import com.ashlikun.camera.scan.BaseCameraScan;
import com.ashlikun.camera.scan.util.CameraXLogUtils;

/**
 * 作者　　: 李坤
 * 创建时间: 2024/2/21　10:14
 * 邮箱　　：496546144@qq.com
 * <p>
 * 功能介绍：相机手势相关
 */
public class CameraXGestureManage {
    /**
     * 定义触摸板之间的最大持续时间（以毫秒为单位）
     * 对给定触摸的触摸和释放被视为点击（点击）
     * 与悬停移动手势相反。
     */
    private static final int HOVER_TAP_TIMEOUT = 150;
    /**
     * 定义触摸板触摸可以移动的最大距离（以像素为单位）
     * 在被释放之前，它被视为点击（点击），而不是
     * 到悬停移动手势。
     */
    private static final int HOVER_TAP_SLOP = 20;
    private BaseCameraScan cameraScan;
    private PreviewView mPreviewView;
    /**
     * 最后点击时间，根据两次点击时间间隔用于区分单机和触摸缩放事件
     */
    private long mLastHoveTapTime;
    /**
     * 是否是点击事件
     */
    private boolean isClickTap;
    /**
     * 按下时X坐标
     */
    private float mDownX;
    /**
     * 按下时Y坐标
     */
    private float mDownY;

    public CameraXGestureManage(BaseCameraScan cameraScan, PreviewView previewView) {
        this.cameraScan = cameraScan;
        this.mPreviewView = previewView;
        init();
    }

    /**
     * 缩放手势检测
     */
    private final ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float scale = detector.getScaleFactor();
            ZoomState zoomState = cameraScan.getZoomState();
            if (zoomState != null) {
                float ratio = zoomState.getZoomRatio();
                // 根据缩放的手势和当前比例进行缩放
                cameraScan.zoomTo(ratio * scale);
                return true;
            }
            return false;
        }
    };
    private final GestureDetector.OnGestureListener mOnGestureListener = new GestureDetector.SimpleOnGestureListener() {
        //是否是变大模式
        private boolean isGoBig = true;

        @Override
        public boolean onDoubleTap(@NonNull MotionEvent e) {
            //双击
            ZoomState zoomState = cameraScan.getZoomState();
            if (zoomState != null) {
                float ratio = zoomState.getZoomRatio();
                if (ratio >= zoomState.getMaxZoomRatio() / 2 && isGoBig) {
                    isGoBig = false;
                } else if (ratio <= zoomState.getMinZoomRatio() && !isGoBig) {
                    isGoBig = true;
                }
                // 根据缩放的手势和当前比例进行缩放
                float result = 0;
                if (zoomState.getLinearZoom() <= 0) {
                    result = ratio + 0.5f;
                } else {
                    if (isGoBig) {
                        result = ratio + zoomState.getLinearZoom();
                    } else {
                        result = ratio - zoomState.getLinearZoom();
                    }
                }
                cameraScan.zoomTo(result);
                return true;
            }
            return false;
        }
    };

    private void init() {
        ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(mPreviewView.getContext(), mOnScaleGestureListener);
        GestureDetector gestureDetector = new GestureDetector(mPreviewView.getContext(), mOnGestureListener);
        mPreviewView.setOnTouchListener((v, event) -> {
            //抬起对焦
            handlePreviewViewClickTap(event);
            if (cameraScan.isNeedTouchZoom()) {
                return gestureDetector.onTouchEvent(event) || scaleGestureDetector.onTouchEvent(event);
            }
            return false;
        });
    }

    /**
     * 处理预览视图点击事件；如果触发的点击事件被判定对焦操作，则开始自动对焦
     *
     * @param event 事件
     */
    private void handlePreviewViewClickTap(MotionEvent event) {
        if (event.getPointerCount() == 1) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isClickTap = true;
                    mDownX = event.getX();
                    mDownY = event.getY();
                    mLastHoveTapTime = System.currentTimeMillis();
                    break;
                case MotionEvent.ACTION_MOVE:
                    isClickTap = distance(mDownX, mDownY, event.getX(), event.getY()) < HOVER_TAP_SLOP;
                    break;
                case MotionEvent.ACTION_UP:
                    if (isClickTap && mLastHoveTapTime + HOVER_TAP_TIMEOUT > System.currentTimeMillis()) {
                        // 开始对焦和测光
                        startFocusAndMetering(event.getX(), event.getY());
                    }
                    break;
            }
        }
    }

    /**
     * 计算两点的距离
     *
     * @param aX a点X坐标
     * @param aY a点Y坐标
     * @param bX b点X坐标
     * @param bY b点Y坐标
     * @return 两点距离
     */
    private float distance(float aX, float aY, float bX, float bY) {
        float xDiff = aX - bX;
        float yDiff = aY - bY;
        return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);
    }

    /**
     * 开始对焦和测光
     *
     * @param x X轴坐标
     * @param y Y轴坐标
     */
    private void startFocusAndMetering(float x, float y) {
        if (cameraScan.getCamera() != null) {
            MeteringPoint point = mPreviewView.getMeteringPointFactory().createPoint(x, y);
            FocusMeteringAction focusMeteringAction = new FocusMeteringAction.Builder(point).build();
            if (cameraScan.getCamera().getCameraInfo().isFocusMeteringSupported(focusMeteringAction)) {
                cameraScan.getCamera().getCameraControl().startFocusAndMetering(focusMeteringAction);
                CameraXLogUtils.d("startFocusAndMetering: " + x + "," + y);
            }
        }
    }
}
